/**
  * Author: Mei
  * Date: 2021-01-07 15:54
  * Description: ioc容器  解决不能创建所有类型对象的问题
  *
  */
//#include "../head.h"
#include "any.h"

//template<class T> //不用指定父接口
class IocContainer {
public:
    IocContainer(void) {
    }

    ~IocContainer(void) {
    }

    //1、为依赖对象时，创建依赖对象和对象本身
    //注册需要创建对象的构造函数，需要传入一个唯一的标识，以便在后面查找
    template<class T, class Depend, typename ...Args>
    typename enable_if<!is_base_of<T, Depend>::value>::type
    RegisterType(const string &strKey, Args &&...args) {
        function<T *()> func = [args...]() {
            return new T(new Depend(args...)); //通过闭包擦除了参数类型
        };
        RegisterType(strKey, func);
    }

    //2、为继承关系时，直接创建派生类对象
    template<class T, class Depend, typename ...Args>
    typename enable_if<is_base_of<T, Depend>::value>::type
    RegisterType(const string &strKey, Args &&...args) {
        function<T *()> func = [args...]() {
            return new Depend(args...); //通过闭包擦除了参数类型
        };
        RegisterType(strKey, func);
    }

    //3、希望能创建普通对象
    template<class T, typename ...Args>
    void
    RegisterSimple(const string &strKey, Args &&...args) {
        function<T *()> func = [args...]() {
            return new T(args...); //通过闭包擦除了参数类型
        };
        RegisterType(strKey, func);
    }

    //根据标识去查找对应的构造器，并创建对象
    template<typename T, typename ...Args>
    T *Resolve(const string &strKey, Args ...args) {
        if (m_creatorMap.find(strKey) == m_creatorMap.end()) {
            return nullptr;
        }
        Any resolver = m_creatorMap[strKey];
        //将any转换为function
        function<T *(Args...)> func = resolver.AnyCast<function<T *(Args...)>>();
        return func(args...);
    }

    //创建智能对象
    template<typename T, typename ...Args>
    shared_ptr<T> ResolvedShared(const string &strKey, Args ...args) {
        T *ptr = Resolve<T>(strKey, args...);
        return shared_ptr<T>(ptr);
    }

private:
    void RegisterType(const string &key, Any constructor) {
        if (m_creatorMap.find(key) != m_creatorMap.end()) {
            throw invalid_argument("this key has already exist！");
        }
        m_creatorMap.emplace(key, constructor);
        //m_creatorMap.insert(make_pair(key, constructor));
    }

private:
    unordered_map<string, Any> m_creatorMap;

};

//测试类
struct ICar {
    virtual ~ICar() {}

    virtual void test() const = 0;
};

struct Bus : ICar {
    Bus(int i, int j) {
        cout << "value i = " << i << ", j=" << j << endl;
    }

    void test() const {
        cout << "Bus::test()" << endl;
    }
};

struct Car : ICar {
    Car() {}

    void test() const {
        cout << "Car::test()" << endl;
    }
};

struct A {
    A(ICar *ptr) : m_ptr(ptr) { //在构造函数中注入了IOC容器的依赖
    }

    void Func() {
        m_ptr->test();
    }

    ~A() {
        if (m_ptr != nullptr) {
            delete m_ptr;
            m_ptr = nullptr;
        }
    }

private:
    ICar *m_ptr;
};

struct cc {
    void Func() const {
        cout << "cc::Func()" << endl;
    }
};

int main() {
    //测试
    IocContainer ioc;
    //有继承关系的
    ioc.RegisterType<A, Bus>("bus", 1, 2);
    ioc.RegisterType<A, Car>("car");
    auto pa = ioc.ResolvedShared<A>("bus");
    pa->Func();
    auto pa1 = ioc.ResolvedShared<A>("car");
    pa1->Func();

    //普通函数
    ioc.RegisterSimple<cc>("cf");
    auto cf = ioc.ResolvedShared<cc>("cf");
    cf->Func();

    return 0;
}
